<html>
  <head>
    <title>UniApp错误规范</title>
  </head>
  <body>
    <script>
      //  错误规范

              /*
                  一、背景

                          小程序平台的错误信息，大多返回的格式是 errCode 和 errMsg.

                          但不同的小程序平台，返回的 errCode 有可能不一样。

                          在实际开发中， uni-app引擎、三方插件、开发者自己的业务代码，都会返回错误，但 errCode 也可能彼此冲突。

                          在同一的错误拦截和 uni统计中，混乱的errCode会造成很多问题。

                          很多错误是由更底层的错误引发的，但值暴露最外城错误难以入手排查，需要暴露更底层的错误。

                          为了进一步规范错误信息格式， uni-app 定义了更完善的错误规范：

                              1、补充了 errSubject ，用于区分不同平台或不同模块的 errCode 相同的情况。

                              2、补充了 cause，用于反馈错误的上一层俩元。比如在 app平台，uni.login Api 返回错误时，可能是底层的三方

                                 社交登录sdk报错了，此时会把三方sdk的错误追加到cause里。


                          从2022-11-11起，DCloud 新增的所有API将使用这台uni错误规范。同时我们推荐所有的插件作业也使用这套规范，

                          在 errSubject中声明自己的插件id.
              */

              /*
                  二、定义

                        所有异步API，都应该通过callback回调返回错误，在回调函数参数中包含错误信息，回调函数参数为UniError类型。

                        完整错误类型定义如下：

                             // 源错误信息
                             interface  SourceError{
                                message:string,
                                subject?:string,
                                code?:number,
                                cause?:SurceError|UniAggrateError
                             }

                             // Uni聚合源错误信息（当有多个源错误时，包装成此类对象）
                             interface UniAggrateError extends SourceError{
                                 errors: Array<SourceError|UniAggregateError>
                             }

                             // uni错误信息
                             interface UniError{
                                errSubject:string,
                                errCode:number,
                                errMsg:string,
                                data?:Object,
                                cause?:SourceError|UniAggregateError
                             }

                             // 回调函数
                             function CallBack(err:UniError){
                             
                             }

                        1、SourceError

                              用于保存引起错误的源错误，如app端三方SDK的错误信息，包括以下属性：

                                  ①、subject 源错误模块名称(如 app端三方sdk),如 uni-AD 中的穿山甲广告SKD的模块名称为"csj"

                                  ②、code 源错误（如app端三方SDK）的原始错误码

                                  ③、message 源错误(如app端三方SDK)的原始错误描述信息

                                  ④、cause 上级源错误，只有一个源错误时是 SourceError，包含多个源错误时封装成 AgrreateError

                              注意：  源错误可以根据业务情况扩展其他属性，如 uni-AD中，可以添加 slotId 来展示聚合的三方广告位标识。

                        2、UniAggregateError

                              用于保存多个源错误，如 app端某个错误嗯嗯是由多个三方SDK的错误引起的，可将多个源错误组成UniAggregateError对象。

                              包括以下属性：

                                      errors 数组，可包含SourceError或 UniAggregateError对象

                        3、UniError

                              Uni统一错误信息，用于统一各平台(端)错误信息：

                                  ①、errSubject 统一错误主题(模块)名称，字符串类型，存在多级模块时使用 "::" 分隔，即 "模块名称::二级模块名称"。
                                    
                                       参考errSubject(模块/主题名称)： https://zh.uniapp.dcloud.io/tutorial/err-spec.html#errsubject

                                  ②、errCode 统一错误代码，数字类型。通常0表示成功，其他为错误码。

                                        对于已经实现的API，继续保留现有errCode规范(保留向下兼容)。

                                        错误码长度及规范参考微信小程序的 Errno错误码：

                                                    https://developers.weixin.qq.com/miniprogram/dev/framework/usability/PublicErrno.html#%E9%94%99%E8%AF%AF%E7%A0%81%E5%88%97%E8%A1%A8

                                        使用7位数错误码，
                                        
                                        第1-2位标识API接口的一级目录，
                                        
                                        第3-4位标识API接口的二级目录，
                                        
                                        第 5-7位表示具体的错误类型。

                                        其他平台，与微信小程序相同的错误，错误码应该尽量保持一致。

                                        定义平台专有错误码时，为了避免冲突，错误码的第 5-7位按以下规则：

                                            -1- 跨端（App/Web）:使用 6xx

                                            -2- App-Android端： 使用 7xx

                                            -3- App-ios端：     使用 8xx

                                            -4- Web端：         使用 9xx

                                            -5- harmony next端：使用 5xx


                                  ③、errMsg 统一错误小数信息，字符串类型，应准确描述引起的错误原因

                                  ④、data(可选) ，错误时返回的数据，比如获取设备信息时，如部分数据获取成功，部分数据获取失败，此时触发错误回调，

                                          需要将获取成功的数据放到data属性中

                                  ⑤、cause(可选)，源错误信息，可以包含多个错误，详见 SourceError

                                        当源错误存在多个时，需要将 SourceError 封装到 AggregateError对象中，
                                        
                                        按以下方式获取 SourceError数组：

                                              function CallBack(err:UniError){
                                                  var cerrs:SourceError[] =err.cause.errors;
                                              }

                        4、errSubject (模块/主题)名称
                                errSubject属性值表示返回错误的调用模块名称。

                                             模块名称              描述

                                             uni-runtime          app端SDK运行环境错误

                                             uni-secure-network   安全网络

                                             uni-ad               uni-ad

                                             uni-push             UniPush

                                             uni-login            OAuth （登录鉴权）

                                             uni-verify           一键登录
                                注意：   
                                
                                    ①、uni内置模块 errSubject 属性值为 "uni-模块英文名称"，如果英文名称由多个单词组成，单词键应该加 "-" 分隔

                                    ②、uni API的 errSubject 属性值

                                            uni.XXX API时 errSubject 属性值为"uni-API"名称，如 uni.getSystemInfo(),错误回调中 errSubject 属性值为 "uni-getSystemInfo"

                                            ObjectXX API时 errSubject 属性值为 "uni-Object名称-API名称"，如 SocketTask.onMessage(),错误回调中 errSubject属性值为 "uni-SocketTask-onMessage"

                                    ③、uni插件中返回错误时建议将 "插件id" 作为errSubject属性值，如果插件的API较多时可将每个API单独定义 errSubject,建议使用errSubject属性值格式为 "插件id-API名称"
              */


              /*
                  三、uts插件或 uvue页面中使用 UniError

                          在 uni-app、uni-app x 中的错误信息建议统一使用 UniError对象，以便在发生错误时统一捕获处理，

                          特别是以下情况：

                                ①、在 uts 插件中封装API给uni-app使用时，返回的错误信息要求使用UniError对象。

                                ②、在uni-app x项目的uvue页面中，抛出错误要求使用UniError对象。

                          在App端， UniError 和 SourceError都是从uts Error类继承。


                          1、构造UniError对象

                                      UniError对象必须通过new操作符构造。

                                    ★、语法：

                                        new UniError(),
                                        new UniError(errSubject:string,errCode:number,errMsg:string)

                                    ★、参数：
                                        ①、errSubject 统一错误主题(模块)名称，字符串类型，存在多级模块时使用 "::"分割，级" 模块名称::二级模块名称"，
                                            
                                                      参考 errSubject (模块/主题)名称： https://uniapp.dcloud.net.cn/tutorial/err-spec.html#errsubject

                                        ②、errCode 统一错误码，数字类型，通常0表示成功，其它为错误码

                                        ③、errMsg 统一错误描述信息，字符串类型，应该准确描述引起的错误原因

                                    ★、示例：
                                        // 创建一个 UniError
                                        let  error = new UniError("uni-apidName",6000,"Custom uni error")

                                        // 设置 data 数据（可选）
                                        error.data ={
                                            "dataName":"custom data value"
                                        }


                          2、构造SourceError对象
                                     
                                    当错误信息是由三方SDK或其他模块引起时，可以将三方SDK或其他模块的错误信息封装在SourceError中作为UniError的源错误：、

                                    ★、语法：

                                          new  SourceErrot()
                                          new  SourceError(message:string)

                                    ★、参数：

                                           message源错误小数信息，字符串类型

                                    ★、示例：

                                           // 创建一个SourceError
                                           let sourceError = new SourceError("Third SDK error message");

                                           // 创建一个 UniError
                                           let  error = new UniError("uni-apiName",60000,"Custom uni error");

                                           // 设置源错误
                                           error.cause = sourceError;



                           3、构造 UniAggregateError对象

                                   当错误时由多个 SourceError源错误引起的时，可以将多个源错误放到一个 UniAggregateError对象中

                                   ★、语法

                                           new  UniAggregateError(errors:Arragy<SourceError>)

                                   ★、参数

                                          errors: 源错误列表 ，Array类型

                                   ★、示例：

                                          // 创建一个UniAggregateError
                                          let aggregateError = new UniAggregateError([new SourceError("First 3rd SDK error message"), new SourceError("Second 3rd SDK error message")]);

                                          // 创建一个UniError
                                          let error = new UniError("uni-apidName",60000,"Custom uni error");

                                          // 设置源错误
                                          error.cause = aggregateError;
              */
    </script>
  </body>
</html> 